function fn() {
    var a = 1;
    let b = 2;
    {
        let b = 3;
        var c = 4;
        let d = 5;
        //console.log(a, b, c, d);//TODO
    }
    {
        let b = 6;
        let d = 7;
        //console.log(a, b, c, d);
    }
}
fn();

/**
 * 1.global编译阶段
 */

let globalEC = {
    this: globalThis,
    outer: null,//外部的执行上下文,词法作用域就是静态作用域，就是指作用域是由代码中函数声明的位置来决定的
    variableEnvironment: {
        fn() { console.log(a, b, c, d) }
    },
    lexicalEnvironment: {}
}


/**
 * 2.fn编译阶段
 */
let fnEC = {
    this: globalThis,
    outer: globalEC,
    variableEnvironment: { a: undefined, c: undefined },
    lexicalEnvironment: [{ b: undefined }]
}
/**
 * 3.编译代码块1
 */
fnEC.variableEnvironment.a = 1;
fnEC.lexicalEnvironment.b = 2;
fnEC.lexicalEnvironment.push({
    b: undefined,
    d: undefined
});
/**
 * 4.执行代码块1
 */

fnEC.lexicalEnvironment[1].b = 3;
fnEC.variableEnvironment.c = 4;
fnEC.lexicalEnvironment[1].d = 5;

console.log(getValue('a', fnEC), getValue('b', fnEC), getValue('c', fnEC), getValue('d', fnEC));
function getValue(name, ec) {
    for (let i = ec.lexicalEnvironment.length - 1; i >= 0; i--) {
        if (name in ec.lexicalEnvironment[i]) {
            return ec.lexicalEnvironment[i][name];
        }
    }
    let currentVariableEnvironment = ec.variableEnvironment;
    while (currentVariableEnvironment) {
        if (name in currentVariableEnvironment) {
            return currentVariableEnvironment[name];
        }
        currentVariableEnvironment = currentVariableEnvironment.outer;
    }
    return null;
}

/**
 * 5.编译代码块2
 */
fnEC.lexicalEnvironment.pop();
fnEC.lexicalEnvironment.push({
    b: undefined,
    d: undefined
});
/**
 * 5.执行代码块2
 */
fnEC.lexicalEnvironment[1].b = 6;
fnEC.lexicalEnvironment[1].d = 7;
console.log(getValue('a', fnEC), getValue('b', fnEC), getValue('c', fnEC), getValue('d', fnEC));

// 1 3 4 5
// 1 6 4 7
